const jwt = require('jsonwebtoken');
const config = require('../config');
const { User } = require('../models');

/**
 * 认证中间件
 * 验证JWT令牌并添加用户到请求对象
 */
const authenticate = async (req, res, next) => {
  try {
    // 获取请求头中的令牌
    const authHeader = req.headers.authorization;
    
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return res.status(401).json({ message: '未提供认证令牌' });
    }
    
    // 提取令牌
    const token = authHeader.split(' ')[1];
    
    if (!token) {
      return res.status(401).json({ message: '未提供认证令牌' });
    }
    
    try {
      // 验证令牌
      const decoded = jwt.verify(token, config.jwt.secret);
      
      // 将用户信息添加到请求对象
      req.user = decoded;
      
      // 继续请求
      next();
    } catch (error) {
      console.error('令牌验证失败:', error);
      
      if (error.name === 'TokenExpiredError') {
        return res.status(401).json({ message: '令牌已过期' });
      }
      
      return res.status(401).json({ message: '无效的令牌' });
    }
  } catch (error) {
    console.error('认证中间件错误:', error);
    res.status(500).json({ message: '服务器内部错误' });
  }
};

/**
 * 授权中间件 - 检查用户是否是管理员
 */
const isAdmin = (req, res, next) => {
  if (req.user && req.user.role === config.roles.ADMIN) {
    return next();
  }
  
  return res.status(403).json({ message: '需要管理员权限' });
};

/**
 * 授权中间件 - 检查用户是否是销售人员
 */
const isSales = (req, res, next) => {
  if (req.user && req.user.role === config.roles.SALES) {
    return next();
  }
  
  return res.status(403).json({ message: '需要销售人员权限' });
};

/**
 * WebSocket认证中间件
 */
const socketAuth = async (socket, next) => {
  try {
    // 尝试从不同位置获取认证令牌
    let token = null;
    
    // 1. 从auth对象获取（推荐方式）
    if (socket.handshake.auth && socket.handshake.auth.token) {
      token = socket.handshake.auth.token;
      console.log('从auth获取token:', token.substring(0, 15) + '...');
    } 
    // 2. 从query参数获取（兼容方式）
    else if (socket.handshake.query && socket.handshake.query.token) {
      token = socket.handshake.query.token;
      console.log('从query获取token:', token.substring(0, 15) + '...');
    }
    // 3. 从headers获取（另一种兼容方式）
    else if (socket.handshake.headers.authorization) {
      const authHeader = socket.handshake.headers.authorization;
      if (authHeader.startsWith('Bearer ')) {
        token = authHeader.substring(7);
      } else {
        token = authHeader;
      }
      console.log('从headers获取token:', token.substring(0, 15) + '...');
    }
    
    if (!token) {
      console.error('Socket连接错误: 未提供认证令牌');
      return next(new Error('未提供认证令牌'));
    }
    
    console.log('正在验证Socket认证令牌:', token.substring(0, 15) + '...');
    console.log('JWT密钥长度:', config.jwt.secret.length);
    console.log('JWT配置:', {
      algorithm: config.jwt.algorithm,
      issuer: config.jwt.issuer,
      expiresIn: config.jwt.expiresIn
    });
    
    try {
      // 检查是否为开发环境的紧急token
      const isEmergencyToken = token.toLowerCase().includes('admin') && process.env.NODE_ENV !== 'production';
      
      // 验证令牌
      let decoded;
      try {
        decoded = jwt.verify(token, config.jwt.secret, {
          algorithms: ['HS256']
        });
        console.log('Token解析成功:', JSON.stringify(decoded));
      } catch (verifyError) {
        console.error('Token验证失败:', verifyError.message);
        
        // 在开发环境中，如果是管理员紧急令牌，允许应急登录
        if (isEmergencyToken && !process.env.NODE_ENV) {
          console.log('应急模式: 使用应急管理员token');
          decoded = { id: 1, username: 'admin', role: 'admin' };
        } else {
          throw verifyError;
        }
      }
      
      // 添加用户信息到socket对象
      socket.user = decoded;
      
      // 在开发/测试环境中，可以跳过用户数据库验证
      if (process.env.NODE_ENV !== 'production' && decoded.username === 'admin') {
        console.log('开发环境: 跳过管理员用户数据库验证');
        return next();
      }
      
      // 查找并验证用户
      try {
        const user = await User.findByPk(decoded.id);
        
        if (!user) {
          console.error(`Socket认证失败: 用户ID=${decoded.id}不存在`);
          return next(new Error('用户不存在'));
        }
        
        if (user.status !== 'active') {
          console.error(`Socket认证失败: 用户ID=${decoded.id}已禁用, 状态=${user.status}`);
          return next(new Error('用户已禁用'));
        }
        
        console.log(`Socket认证成功: 用户ID=${user.id}, 用户名=${user.username}`);
        
        // 继续连接
        next();
      } catch (dbError) {
        console.error('查询用户数据库失败:', dbError);
        
        // 在开发环境中，允许应急授权
        if (process.env.NODE_ENV !== 'production' && decoded.username === 'admin') {
          console.log('数据库错误，但在开发环境中继续允许管理员连接');
          return next();
        }
        
        return next(new Error('用户验证失败'));
      }
    } catch (error) {
      console.error('Socket认证失败:', error.message);
      
      if (error.name === 'TokenExpiredError') {
        return next(new Error('令牌已过期'));
      }
      
      return next(new Error('无效的令牌'));
    }
  } catch (error) {
    console.error('Socket认证中间件错误:', error);
    next(new Error('服务器内部错误'));
  }
};

module.exports = {
  authMiddleware: authenticate,
  authenticate,
  isAdmin,
  isSales,
  socketAuth
}; 